#!/usr/bin/env python3

#==============================================================================
# Functionality
#==============================================================================

# utility funcs, classes, etc go here.

#==============================================================================
# Cmdline
#==============================================================================
import argparse

parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, 
    description="""
TODO
""")
     
parser.add_argument('-v', '--verbose',
    action="store_true",
    help="verbose output" )
     
parser.add_argument('-r', '--reverse',
    action="store_true",
    help="reverse sort order" )
     
parser.add_argument('-i', '--ignore-case',
    action="store_true",
    help="ignore case sensitivity" )
     
     
# parser.add_argument('--ignore-sign',
    # action="store_false",
    # help="by default, sort args as signed numbers" )

args = None

#==============================================================================
# Main
#==============================================================================
import sys
import pdb
import natsort

# def main():
#     lines = [line for line in sys.stdin]
#     for line in natsort.natsorted(lines, reverse=args.reverse, alg=natsort.ns.REAL):
#         sys.stdout.write(line)

# if __name__ == "__main__":
#     args = parser.parse_args()
#     main()


# https://stackoverflow.com/questions/14693701/how-can-i-remove-the-ansi-escape-sequences-from-a-string-in-python

import re
# 7-bit and 8-bit C1 ANSI sequences
ansi_escape_8bit = re.compile(br"""
    (?: # either 7-bit C1, two bytes, ESC Fe (omitting CSI)
        \x1B
        [@-Z\\-_]
    |   # or a single 8-bit byte Fe (omitting CSI)
        [\x80-\x9A\x9C-\x9F]
    |   # or CSI + control codes
        (?: # 7-bit CSI, ESC [ 
            \x1B\[
        |   # 8-bit CSI, 9B
            \x9B
        )
        [0-?]*  # Parameter bytes
        [ -/]*  # Intermediate bytes
        [@-~]   # Final byte
    )
""", re.VERBOSE)

# import sys
# for line in sys.stdin.buffer:
#   result = ansi_escape_8bit.sub(b"", line)
#   sys.stdout.buffer.write(result)


def run():
    if args.verbose:
        print(args)
    # if len(args.args) <= 0 and not has_stdin():
    #     # if there were no args and there was no input, prompt user.
    #     print 'Enter input (press Ctrl-D when done):'
    # if len(args.args) <= 0 or has_stdin():
    #     indata = sys.stdin.read()
    # lines = [line for line in sys.stdin]
    # lines = sys.stdin.buffer.read().splitlines(keepends=True)
    lines = sys.stdin.buffer
    # alg = 0
    # alg = natsort.ns.LOCALE
    alg = natsort.ns.LOCALE | natsort.ns.PATH
    if args.ignore_case:
        alg |= natsort.ns.IGNORECASE
    else:
        alg |= natsort.ns.CAPITALFIRST
    def sortkey(line):
      # strip leading whitespace.
      line = line.lstrip()
      # strip terminal escape codes (colorization, etc).
      line = ansi_escape_8bit.sub(b"", line)
      # decode as string. Try UTF-8 first, then fall back to latin1 if we get an error.
      try:
        line = line.decode('utf-8')
      except UnicodeDecodeError:
        line = line.decode('latin1')
      # use this as the sort key.
      return line
    for line in natsort.natsorted(lines, reverse=args.reverse, key=sortkey, alg=alg):#, alg=natsort.ns.REAL): # caused problems with lltime
        sys.stdout.buffer.write(line)

def main():
    try:
        global args
        if not args:
            args, leftovers = parser.parse_known_args()
            args.args = leftovers
        return run()
    except IOError:
        # http://stackoverflow.com/questions/15793886/how-to-avoid-a-broken-pipe-error-when-printing-a-large-amount-of-formatted-data
        try:
            sys.stdout.close()
        except IOError:
            pass
        try:
            sys.stderr.close()
        except IOError:
            pass

if __name__ == "__main__":
    main()
